package command

import (
	"database/sql"
	"fmt"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

type Stats struct {
	S0C   float64 `json:"S0C"`
	S1C   float64 `json:"S1C"`
	S0U   float64 `json:"S0U"`
	S1U   float64 `json:"S1U"`
	EC    float64 `json:"EC"`
	EU    float64 `json:"EU"`
	OC    float64 `json:"OC"`
	OU    float64 `json:"OU"`
	MC    float64 `json:"MC"`
	MU    float64 `json:"MU"`
	CCSC  float64 `json:"CCSC"`
	CCSU  float64 `json:"CCSU"`
	YGC   int     `json:"YGC"`
	YGCT  float64 `json:"YGCT"`
	FGC   int     `json:"FGC"`
	FGCT  float64 `json:"FGCT"`
	GCT   float64 `json:"GCT"`
}

// 要执行的命令
var command = "jstat -gc "

func parseData(data string) *Stats {
	values := regexp.MustCompile(`\d+(\.\d+)?`).FindAllString(data, -1)
	lines := regexp.MustCompile(`\n`).Split(data, -1)
	if len(lines) >= 2 {
		values = regexp.MustCompile(`\s+`).Split(lines[1], -1)
		fmt.Println(values)
		fmt.Println("data len: " + strconv.Itoa(len(values)))
	}
	if len(values) == 17 || (len(values) == 18 && values[17] == "") {
		s0c, _ := strconv.ParseFloat(values[0], 64)
		s1c, _ := strconv.ParseFloat(values[1], 64)
		s0u, _ := strconv.ParseFloat(values[2], 64)
		s1u, _ := strconv.ParseFloat(values[3], 64)
		ec, _ := strconv.ParseFloat(values[4], 64)
		eu, _ := strconv.ParseFloat(values[5], 64)
		oc, _ := strconv.ParseFloat(values[6], 64)
		ou, _ := strconv.ParseFloat(values[7], 64)
		mc, _ := strconv.ParseFloat(values[8], 64)
		mu, _ := strconv.ParseFloat(values[9], 64)
		ccsc, _ := strconv.ParseFloat(values[10], 64)
		ccsu, _ := strconv.ParseFloat(values[11], 64)
		ygc, _ := strconv.Atoi(values[12])
		ygct, _ := strconv.ParseFloat(values[13], 64)
		fgc, _ := strconv.Atoi(values[14])
		fgct, _ := strconv.ParseFloat(values[15], 64)
		gct, _ := strconv.ParseFloat(values[16], 64)

		return &Stats{
			S0C:   s0c,
			S1C:   s1c,
			S0U:   s0u,
			S1U:   s1u,
			EC:    ec,
			EU:    eu,
			OC:    oc,
			OU:    ou,
			MC:    mc,
			MU:    mu,
			CCSC:  ccsc,
			CCSU:  ccsu,
			YGC:   ygc,
			YGCT:  ygct,
			FGC:   fgc,
			FGCT:  fgct,
			GCT:   gct,
		}
	} else {
		return nil
	}
}

func saveExecutionStats(stats *Stats, taskID, executorID string, db *sql.DB) {
	// 创建MySQL数据库连接配置

	// 插入结果到数据库的execution_stats表中
	insertQuery := `
		INSERT INTO execution_stats (S0C, S1C, S0U, S1U, EC, EU, OC, OU, MC, MU, CCSC, CCSU, YGC, YGCT, FGC, FGCT, GCT, task_id, executor_id)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`
	_, err := db.Exec(insertQuery,
		stats.S0C,
		stats.S1C,
		stats.S0U,
		stats.S1U,
		stats.EC,
		stats.EU,
		stats.OC,
		stats.OU,
		stats.MC,
		stats.MU,
		stats.CCSC,
		stats.CCSU,
		stats.YGC,
		stats.YGCT,
		stats.FGC,
		stats.FGCT,
		stats.GCT,
		taskID,
		executorID,
	)
	if err != nil {
		log.Println("Failed to insert execution stats into database:", err)
		return
	}

	log.Println("Execution stats saved into database successfully.")
}

func ExecuteStatCommand(pid, taskID, executorID string, db *sql.DB) {
	// 执行cmd命令获取返回值
	parts := strings.Fields(command + pid)
	cmd := exec.Command(parts[0], parts[1:]...)
	// cmd := exec.Command(command + pid)
	output, err := cmd.Output()
	if err != nil {
		log.Println("Failed to execute command:", err)
		return
	}

	stats := parseData(string(output))
	if stats != nil {
		// 保存执行信息到数据库
		saveExecutionStats(stats, taskID, executorID, db)
		log.Println("Command executed and stats saved into database successfully.")
	} else {
		log.Println("Failed to parse data:\n", string(output))
	}
}

func SetJstat(jstatCmd string) {
	command = jstatCmd + " -gc "
	log.Println("use cmd: " + command)
}